// # rollup.config.js
import json from '@rollup/plugin-json' // 它允许从JSON 文件中直接导入数据
import { nodeResolve } from '@rollup/plugin-node-resolve' //(该插件可以让Rollup在打包过程中解析和处理Node.js模块的导入（import）语句) 由于不像webpack一样可以默认导入第三方插件的模块，需要安装 @rollup/plugin-node-resolve插件来实现，通过Node解析算法定位模块，来获取node_modules的第三方模块
import commonjs from '@rollup/plugin-commonjs' // 该插件通过Ast方式，将原本的 CommonJS 模块转换为了 ES6 模块的语法 (Rollup默认支持ESM模式，由于大多npm库使用了commonJS 模式，为了兼容我们需要通过 @rollup/plugin-commonjs 插件对这部分做兼容处理。)
import terser from '@rollup/plugin-terser' // 该插件会将打包输出的js文件进行压缩，从而达到减小代码打包体积的目的。(如果你熟悉webapck,不难发现它与terser-webpack-plugin的功能是差不多的。)
import del from 'rollup-plugin-delete' // 在每次运行 Rollup 打包之前删除先前生成的打包内容
import alias from '@rollup/plugin-alias' //使用这个插件，你可以在引入文件时，使用一个 别名 来代替那些固定的路径。
import strip from '@rollup/plugin-strip' //用于从代码中删除 debugger 语句和诸如 assert.equal 和 console.log 类似的函数。
import replace from '@rollup/plugin-replace' //一个 Rollup 插件，在打包时替换文件中的目标字符串。
import run from '@rollup/plugin-run' // 一个 Rollup 插件，一旦你的 bundle 被构建，它就会在 nodejs 中运行。

// 需先安装 pnpm add @babel/core @babel/preset-env @babel/plugin-transform-class-properties -D
import babel from '@rollup/plugin-babel' // 使用本插件，可以通过 Babel 的能力将你所写的 es6/es7 代码编译转换为 es5 的，以适用那些更古老的浏览器。https://juejin.cn/post/7264044879209529381#heading-10
import progress from 'rollup-plugin-progress' // 显示由汇总包传送的当前模块。 https://www.npmjs.com/package/rollup-plugin-progress
import typescript from 'rollup-plugin-typescript2' // 处理typescript

import replaceHelloWorld from './rullup_plugins/replace-helloworld.mjs' // 接下来在rollup.config.js中使用

// https://segmentfault.com/q/1010000042241121 (node执行中，import引用json文件失败？)
import * as fs from 'fs'
import { glob } from 'glob'
import path from 'path'
import dayjs from 'dayjs'
import { defaultsDeep } from 'lodash-es'
const packageData = JSON.parse(fs.readFileSync('./package.json', 'utf8'))
const { version, author } = packageData
const isProduction = process.env.NODE_ENV === 'production'

const someCommonConfig = (dir, format) => {
  let tsConfig = path.resolve(process.cwd(), 'tsconfig.json')
  if (format == 'cjs') {
    tsConfig = path.resolve(process.cwd(), 'tsconfig-cjs.json')
  }
  return {
    watch: {
      // 配置监听处理
      exclude: 'node_modules/**'
    },
    // 为了防止其他插件对 CommonJS 检测产生影响，一般放在其他插件之前。如果有使用Bable解析的，可以将它放在 commonjs 插件之前。
    // https://github.com/rollup/plugins/tree/master/packages
    plugins: [
      progress({
        clearLine: true // default: true
      }),
      alias({
        entries: [
          {
            find: '@',
            replacement: path.resolve('./src')
          }
        ]
      }),
      commonjs(),
      json(),
      nodeResolve(),
      typescript({
        tsconfig: tsConfig,
        tsconfigOverride: {
          include: ['src/**/*.ts', 'src/**/*.d.ts', 'src/**/type1.d.ts'],
          compilerOptions: {
            declaration: true,
            declarationDir: 'dist/types'
          }
        },
        clean: true, // 设置为 true 可禁用缓存并执行全新生成。这也会擦除任何现有缓存。
        useTsconfigDeclarationDir: true // 默认情况下，声明文件将与生成的 Rollup 捆绑包位于同一目录中。如果要覆盖此行为并改用 declarationDir ，请在插件选项中设置
      }), // TypeScript 插件放在 babel() 插件之前
      babel({
        babelrc: false,
        babelHelpers: 'bundled', //这意味着 Babel 会将帮助函数打包到每个文件中，而不是引入外部的辅助函数。这样可以减少对外部辅助函数的依赖，但可能会导致每个文件都包含了一份辅助函数的副本。
        presets: [['@babel/preset-env', { modules: 'auto', loose: true }]],
        plugins: [
          ['@babel/plugin-transform-class-properties', { loose: true }]
        ],
        exclude: 'node_modules/**'
      }),
      replace({
        __build_time__: dayjs().format('YYYY-MM-DD HH:mm:ss'),
        preventAssignment: true
      }),
      isProduction &&
        // https://www.npmjs.com/package/@rollup/plugin-strip
        strip({
          // functions: ['console.log'],
          functions: [], // 默认['console.*']
          debugger: true // 如果 true 指示插件删除调试器语句。默认：true
        }),
      isProduction && terser(),
      del({ targets: dir })
    ],
    output: {
      banner: '/* rollup_0 version ' + version + ' */',
      footer: `/* follow me on github! ${author} */`,
      generatedCode: 'es5', // 默认
      sourcemap: !isProduction
    }
  }
}

// ! 直接数组output时是根据数组的顺序来的
export default [
  defaultsDeep(
    {
      // 多入口  https://cn.rollupjs.org/configuration-options/#input
      input: {
        index: path.resolve(process.cwd(), 'src/index.js'),
        index2: path.resolve(process.cwd(), 'src/index2.js'),
        'utils/index': path.resolve(process.cwd(), 'src/utils/index.js')
      },
      output: {
        // file: 'dist/es/bundle.esm.js', //该选项用于指定要写入的文件。如果适用的话，也可以用于生成 sourcemap。只有在生成的 chunk 不超过一个的情况下才可以使用。
        dir: 'dist/es', // 该选项用于指定所有生成的 chunk 被放置在哪个目录中。如果生成一个以上的 chunk，那么这个选项是必需的。否则，可以使用 file 选项来代替。
        format: 'es',
        // 入口文件（即主要模块）的文件名规则
        entryFileNames: (entryInfo) => {
          // console.log('🚀💥💥 ~ entryInfo: --》》', entryInfo)
          return 'entry-[name].mjs'
        },
        // 用于手动配置模块的代码分割 (如: vendors是下面chunkFileNames的[name]占位符内容) https://www.rollupjs.com/configuration-options/#output-manualchunks
        manualChunks: {
          vendors: ['lodash-es']
        },
        // 其他（拆分文件）异步加载的模块的文件名规则
        chunkFileNames: (ChunkInfo) => {
          return 'chunks/[name]-[hash:6].js'
        },
        banner: '/* rollup_0 version ' + version + ' */',
        footer: `/* follow me on github! ${author} */`,
        generatedCode: 'es5', // 默认
        /*
        default，等于最终导出等于export default xxx，这里适用于单个文件入口
        named，等于export default {xxx1, xxx2}，适用于多个入口文件
        none，没有export，适用于打包web应用，不需要对外抛出对象
        */
        exports: 'auto' // https://www.rollupjs.com/configuration-options/#output-exports
        // sourcemap: false
      }
    },
    someCommonConfig('dist/es')
  ),
  defaultsDeep(
    {
      input: 'src/index.js',
      output: {
        // file: 'dist/iife/bundle.iife.js',//该选项用于指定要写入的文件。如果适用的话，也可以用于生成 sourcemap。只有在生成的 chunk 不超过一个的情况下才可以使用。// pnpm run build_prd
        dir: 'dist/iife',
        format: 'iife',
        banner: '/* rollup_0 version ' + version + ' */',
        footer: `/* follow me on github! ${author} */`,
        name: 'firstRollup', // 以umd 或 iife 规范打包后的代码，需要注册在全局对象中的名字
        exports: 'named',
        plugins: [isProduction && terser()],
        // output.globals，用来忽略打包（umd 或 iife 规范）后的代码的代码依赖，比如：代码中依赖jquery，且jquery在代码使用$标识，则可以配置:
        globals: {
          // jquery: '$'
        }
      }
    },
    someCommonConfig('dist/iife', 'iife')
  )
  // defaultsDeep(
  //   {
  //     input: {
  //       index: 'src/index.js',
  //       index2: 'src/index2.js',
  //       'utils/index': 'src/utils/index.js'
  //     },
  //     output: {
  //       // file: 'dist/iife/bundle.iife.js',//该选项用于指定要写入的文件。如果适用的话，也可以用于生成 sourcemap。只有在生成的 chunk 不超过一个的情况下才可以使用。// pnpm run build_prd
  //       dir: 'dist/cjs',
  //       format: 'cjs', // 输出模块格式为 CommonJS
  //       // 入口文件（即主要模块）的文件名规则
  //       entryFileNames: (entryInfo) => {
  //         // console.log('🚀💥💥 ~ entryInfo: --》》', entryInfo)
  //         return 'entry-[name].cjs'
  //       },
  //       // 用于手动配置模块的代码分割 (如: vendors为下面chunkFileNames的[name]占位符内容)
  //       manualChunks: {
  //         vendors: ['lodash-es']
  //       },
  //       // 其他（拆分文件）异步加载的模块的文件名规则
  //       chunkFileNames: (ChunkInfo) => {
  //         return 'chunks/[name]-[hash:6].cjs'
  //       },
  //       banner: '/* rollup_0 version ' + version + ' */',
  //       footer: `/* follow me on github! ${author} */`,
  //       exports: 'named',
  //       plugins: [isProduction && terser()],
  //       // output.globals，用来忽略打包（umd 或 iife 规范）后的代码的代码依赖，比如：代码中依赖jquery，且jquery在代码使用$标识，则可以配置:
  //       globals: {
  //         // jquery: '$'
  //       }
  //     }
  //   },
  //   someCommonConfig('dist/cjs', 'cjs')
  // ),
  // @自定义插件测试
  // {
  //   input: './rullup_plugins/replace-helloworld.mjs',
  //   plugins: [
  //     replaceHelloWorld(),
  //     babel({
  //       babelrc: false,
  //       babelHelpers: 'bundled', //这意味着 Babel 会将帮助函数打包到每个文件中，而不是引入外部的辅助函数。这样可以减少对外部辅助函数的依赖，但可能会导致每个文件都包含了一份辅助函数的副本。
  //       presets: [['@babel/preset-env', { modules: false, loose: true }]],
  //       plugins: [
  //         ['@babel/plugin-transform-class-properties', { loose: true }]
  //       ],
  //       exclude: 'node_modules/**'
  //     }),
  //     // 这个run插件只能在singleEntry中用 （同时node执行的时候也是要看是什么模式，一般根据package.json的type，但是我们这里的package.json的生成是script脚本是较为晚些的，所以我们这里esm的时候就输出.mjs结尾的esmodule模式的js文件）
  //     !isProduction && run()
  //   ], // 由我们的插件解析
  //   output: [
  //     {
  //       dir: 'dist/plugins',
  //       format: 'esm',
  //       entryFileNames: (entryInfo) => {
  //         // console.log('🚀💥💥 ~ entryInfo: --》》', entryInfo)
  //         return '[name].mjs'
  //       }
  //     }
  //   ]
  // }
]

function getUtilsModules() {
  let files = glob.sync('src/utils/*.js')
  //  files = files.map((file) => file.replace(/^src(\/|\\+)/, ''))
  console.log(files)
  return files
}
